package com.demo.security.cloud.servicecenter.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.demo.security.cloud.servicecenter.util.EncryptUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        Object authentication = SecurityContextHolder.getContext().getAuthentication();
        log.error(JSON.toJSONString(authentication));
        if (authentication instanceof OAuth2Authentication){
            log.info("最开始的getOAuth2Request>>>>" + JSON.toJSONString(((OAuth2Authentication) authentication).getOAuth2Request()));
            log.info("最开始的getUserAuthentication>>>>" + JSON.toJSONString(((OAuth2Authentication) authentication).getUserAuthentication()));
        }
        OAuth2Request oAuth2Request = ((OAuth2Authentication)authentication).getOAuth2Request();
        Authentication userAuthentication = ((OAuth2Authentication) authentication).getUserAuthentication();

        String token = request.getHeader("json-token");
        if (token == null) {
            System.err.println("Noting to get token");
            filterChain.doFilter(request, response);
            return;
        }
        // 必须要有token才可以访问
        JSONObject jsonToken = JSON.parseObject(EncryptUtil.decodeUTF8StringBase64(token));
        String userName = null;
        if (jsonToken.get("principal") != null){
            userName = jsonToken.get("principal").toString();
        }
        JSONArray authoritiesArray = jsonToken.getJSONArray("authorities");
        String[] authorities;
        if (jsonToken.get("principal") != null) {
            authorities = authoritiesArray.toArray(new String[authoritiesArray.size()]);
            // 新建并填充到用户身份对象中
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                    userName, null, AuthorityUtils.createAuthorityList(authorities));
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

            // 这里必须要使用OAuth2Authentication来，因为请求中包含Scope和用户权限。不能仅使用UsernamePasswordAuthenticationToken
            // 作为参数传入，不能进行#oauth2.hasScope('ROLE_API')的鉴权。而且，本来放入的类型也应该是OAuth2Authentication
            OAuth2Authentication newOne = new OAuth2Authentication(oAuth2Request, authenticationToken);
            // 设置到当前请求的SecurityContextHolder
            SecurityContextHolder.getContext().setAuthentication(newOne);
        }

        // 继续放行过滤器
        filterChain.doFilter(request, response);
    }
}
